﻿using System;
using System.Runtime.InteropServices;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace TD
{
    partial class InputManager
    {
        private MouseState previousMouseState;
        private MouseState currentMouseState;
        private Point cursorLocation;

        private void InitializeMouse()
        {
            // Initialize them when starting and with the same values.
            previousMouseState = Mouse.GetState();
            currentMouseState = previousMouseState;

            // Initialize the cursor location.
            cursorLocation = new Point(0, 0);
        }

        private void UpdateMouse(GameTime gameTime)
        {
            // Update both states.
            previousMouseState = currentMouseState;
            currentMouseState = Mouse.GetState();

            // Update the cursor location.
            cursorLocation = GetCursorPosition(base.Game);
        }

        /// <summary>
        /// Indicates whether or not the cursor is hovering the given rectangle.
        /// </summary>
        /// <param name="rectangle">The rectangle for which to determine if it is being hovered.</param>
        /// <returns>True when the mouse is hovering the rectangle.</returns>
        public bool IsHover(Rectangle rectangle)
        {
            return IsHover(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
        }

        /// <summary>
        /// Indicates whether or not the cursor is hovering the given rectangle.
        /// </summary>
        /// <param name="x">The X-offset of the rectangle.</param>
        /// <param name="y">The Y-offset of the rectangle.</param>
        /// <param name="width">The width of the rectangle.</param>
        /// <param name="height">The height of the rectangle.</param>
        /// <returns>True when the mouse is hovering the rectangle.</returns>
        public bool IsHover(int x, int y, int width, int height)
        {
            if (x >= cursorLocation.X && (x + width) <= cursorLocation.X)
            {
                if (y >= cursorLocation.Y && (y + height) <= cursorLocation.Y)
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Get the position of the mouse within the game's window.
        /// </summary>
        /// <param name="game">The game from which we want the mouse coordinates relative to its window.</param>
        /// <returns>The coordinates within the game's window.</returns>
        private Point GetCursorPosition(Game game)
        {
            // The point.
            _POINT point;

            // Get the absolute position of the mouse.
            if (GetCursorPos(out point))
            {
                // Convert the position on the screen to the absolute position on the client rectangle.
                if (ScreenToClient(game.Window.Handle, out point))
                {
                    // Ensure that the value of the X-axis is within the window's client rectangle.
                    if (point.X >= 0 && point.X < game.Window.ClientBounds.Width)
                    {
                        // Ensure that the value of the Y-axis is within the window's client rectangle.
                        if (point.Y >= 0 && point.Y < game.Window.ClientBounds.Height)
                        {
                            return new Point(point.X, point.Y);
                        }
                    }

                    // Hold the old location.
                    //return this.cursorLocation;
                }
            }

            // Return the top-left corner when we have failed to get the position.
            //   Or when the cursor is out of the bounds of the client rectangle.
            return new Point(0, 0);
        }

        /// <summary>
        /// Get the location of the mouse within the client area.
        /// </summary>
        /// <returns>The location of the mouse.</returns>
        public Point GetMouseLocation()
        {
            return cursorLocation;
        }

        /// <summary>
        /// Determine whether or not the left mouse button has been pressed.
        /// </summary>
        /// <returns>True when the left mouse button has been pressed. False when it's not.</returns>
        public bool IsMouseClicked()
        {
            return (previousMouseState.LeftButton == ButtonState.Pressed &&
                currentMouseState.LeftButton == ButtonState.Released);
        }

        /// <summary>
        /// Determine whether or not the left mouse button is currently down.
        /// </summary>
        /// <returns>True when the left mouse button is down. False when it's not.</returns>
        public bool IsMouseDown()
        {
            return (currentMouseState.LeftButton == ButtonState.Pressed);
        }

        /// <summary>
        /// Determine whether or not the left mouse button is currently up.
        /// </summary>
        /// <returns>True when the left mouse button is up. False when it's not.</returns>
        public bool IsMouseUp()
        {
            return (currentMouseState.LeftButton == ButtonState.Released);
        }
    }
}
